//
//  GONMarkupParserUtils.m
//  GONMarkupParserSample
//
//  Created by Nicolas Goutaland on 08/08/14.
//  Copyright (c) 2014 Nicolas Goutaland. All rights reserved.
//
//  http://www.w3schools.com/charsets/ref_html_entities_4.asp

#import "GONMarkupParserUtils.h"
#import "GONMarkupParserManager.h"

#define HTML_ENTITY_REGEX               @"&#?[a-zA-Z0-9]+;"
#define HTML_ENTITY_256_PREFIX_SEARCH   @"&#0"
#define HTML_ENTITY_256_PREFIX_REPLACE  @"&#"
#define HTML_ENTITY_256_LENGTH          6

@implementation GONMarkupParserUtils
#pragma mark - Utils
+ (void)cleanHTMLEntitiesFromString:(NSMutableString *)inputString
{
    static NSRegularExpression *regex = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        regex = [NSRegularExpression regularExpressionWithPattern:HTML_ENTITY_REGEX
                                                          options:0
                                                            error:nil];
    });

    NSRange range                = NSMakeRange(0, inputString.length);
    NSTextCheckingResult *result = nil;
    NSString *entity             = nil;
    NSString * match             = nil;
    while ((result = [regex firstMatchInString:inputString options:0 range:range]) != nil) {

        // Check if entity is known
        match  = [inputString substringWithRange:result.range];
        entity = [dicEntities objectForKey:match];

        // If no entity found, try with alternate synthax
        if (!entity)
        {
            // Check only if
            if (match.length == HTML_ENTITY_256_LENGTH && [match rangeOfString:HTML_ENTITY_256_PREFIX_SEARCH].location == 0)
            {
                match = [match stringByReplacingOccurrencesOfString:HTML_ENTITY_256_PREFIX_SEARCH withString:HTML_ENTITY_256_PREFIX_REPLACE];

                // Look again for entity
                entity = [dicEntities objectForKey:match];
            }
        }

        if (entity)
            [inputString replaceCharactersInRange:result.range withString:entity];

        // Update range
        range = NSMakeRange(result.range.location + 1, inputString.length - result.range.location - 1);

        // Break if reaching end of string
        if (range.location + range.length > inputString.length)
            break;
    };
}

+ (NSAttributedString *)attributedString:(GONMarkupParser *)parser
                              withString:(NSString *)inputString
                             defautColor:(UIColor *)defaultColor
                             defaultFont:(UIFont *)defaultFont
                        defaultAlignment:(NSTextAlignment)defaultAlignment
{
    GONMarkupParser *selectedParser = parser;
    if (!selectedParser)
        selectedParser = [GONMarkupParserManager sharedParser];
    
    // Hold initial default configuration
    NSDictionary *defaultConfiguration = [selectedParser.defaultConfiguration copy];
    
    // Check if parser has default configuration for color / font / alignment. If not, use default configuration
    // Text color
    if (![selectedParser.defaultConfiguration objectForKey:NSForegroundColorAttributeName])
    {
        [selectedParser.defaultConfiguration setObject:(defaultColor ? defaultColor : [UIColor blackColor])
                                                forKey:NSForegroundColorAttributeName];
    }
    
    // Font
    if (![selectedParser.defaultConfiguration objectForKey:NSFontAttributeName] && defaultFont)
    {
        [selectedParser.defaultConfiguration setObject:defaultFont
                                                forKey:NSFontAttributeName];
    }
    
    // Alignment
    if (![selectedParser.defaultConfiguration objectForKey:NSParagraphStyleAttributeName])
    {
        NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
        paragraphStyle.alignment = defaultAlignment;
        [selectedParser.defaultConfiguration setObject:paragraphStyle
                                                forKey:NSParagraphStyleAttributeName];
    }
    
    // Compute attributed string
    NSAttributedString *attributedString = [selectedParser attributedStringFromString:inputString
                                                                                error:nil];
    
    // Reset default configuration
    [selectedParser.defaultConfiguration removeAllObjects];
    [selectedParser.defaultConfiguration addEntriesFromDictionary:defaultConfiguration];
    
    
    return attributedString;
}

#pragma mark - Config
static NSDictionary *dicEntities;
+ (void)initialize
{
    [super initialize];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        dicEntities = @{
                        @"&quot;" : @"\"",
                        @"&amp;" : @"&",
                        @"&apos;" : @"'",
                        @"&lt;" : @"<",
                        @"&gt;" : @">",
                        @"&nbsp;" : @"\u00A0",
                        @"&iexcl;" : @"\u00A1",
                        @"&cent;" : @"\u00A2",
                        @"&pound;" : @"\u00A3",
                        @"&curren;" : @"\u00A4",
                        @"&yen;" : @"\u00A5",
                        @"&brvbar;" : @"\u00A6",
                        @"&sect;" : @"\u00A7",
                        @"&uml;" : @"\u00A8",
                        @"&copy;" : @"\u00A9",
                        @"&ordf;" : @"\u00AA",
                        @"&laquo;" : @"\u00AB",
                        @"&not;" : @"\u00AC",
                        @"&shy;" : @"\u00AD",
                        @"&reg;" : @"\u00AE",
                        @"&macr;" : @"\u00AF",
                        @"&deg;" : @"\u00B0",
                        @"&plusmn;" : @"\u00B1",
                        @"&sup2;" : @"\u00B2",
                        @"&sup3;" : @"\u00B3",
                        @"&acute;" : @"\u00B4",
                        @"&micro;" : @"\u00B5",
                        @"&para;" : @"\u00B6",
                        @"&middot;" : @"\u00B7",
                        @"&cedil;" : @"\u00B8",
                        @"&sup1;" : @"\u00B9",
                        @"&ordm;" : @"\u00BA",
                        @"&raquo;" : @"\u00BB",
                        @"&frac14;" : @"\u00BC",
                        @"&frac12;" : @"\u00BD",
                        @"&frac34;" : @"\u00BE",
                        @"&iquest;" : @"\u00BF",
                        @"&Agrave;" : @"\u00C0",
                        @"&Aacute;" : @"\u00C1",
                        @"&Acirc;" : @"\u00C2",
                        @"&Atilde;" : @"\u00C3",
                        @"&Auml;" : @"\u00C4",
                        @"&Aring;" : @"\u00C5",
                        @"&AElig;" : @"\u00C6",
                        @"&Ccedil;" : @"\u00C7",
                        @"&Egrave;" : @"\u00C8",
                        @"&Eacute;" : @"\u00C9",
                        @"&Ecirc;" : @"\u00CA",
                        @"&Euml;" : @"\u00CB",
                        @"&Igrave;" : @"\u00CC",
                        @"&Iacute;" : @"\u00CD",
                        @"&Icirc;" : @"\u00CE",
                        @"&Iuml;" : @"\u00CF",
                        @"&ETH;" : @"\u00D0",
                        @"&Ntilde;" : @"\u00D1",
                        @"&Ograve;" : @"\u00D2",
                        @"&Oacute;" : @"\u00D3",
                        @"&Ocirc;" : @"\u00D4",
                        @"&Otilde;" : @"\u00D5",
                        @"&Ouml;" : @"\u00D6",
                        @"&times;" : @"\u00D7",
                        @"&Oslash;" : @"\u00D8",
                        @"&Ugrave;" : @"\u00D9",
                        @"&Uacute;" : @"\u00DA",
                        @"&Ucirc;" : @"\u00DB",
                        @"&Uuml;" : @"\u00DC",
                        @"&Yacute;" : @"\u00DD",
                        @"&THORN;" : @"\u00DE",
                        @"&szlig;" : @"\u00DF",
                        @"&agrave;" : @"\u00E0",
                        @"&aacute;" : @"\u00E1",
                        @"&acirc;" : @"\u00E2",
                        @"&atilde;" : @"\u00E3",
                        @"&auml;" : @"\u00E4",
                        @"&aring;" : @"\u00E5",
                        @"&aelig;" : @"\u00E6",
                        @"&ccedil;" : @"\u00E7",
                        @"&egrave;" : @"\u00E8",
                        @"&eacute;" : @"\u00E9",
                        @"&ecirc;" : @"\u00EA",
                        @"&euml;" : @"\u00EB",
                        @"&igrave;" : @"\u00EC",
                        @"&iacute;" : @"\u00ED",
                        @"&icirc;" : @"\u00EE",
                        @"&iuml;" : @"\u00EF",
                        @"&eth;" : @"\u00F0",
                        @"&ntilde;" : @"\u00F1",
                        @"&ograve;" : @"\u00F2",
                        @"&oacute;" : @"\u00F3",
                        @"&ocirc;" : @"\u00F4",
                        @"&otilde;" : @"\u00F5",
                        @"&ouml;" : @"\u00F6",
                        @"&divide;" : @"\u00F7",
                        @"&oslash;" : @"\u00F8",
                        @"&ugrave;" : @"\u00F9",
                        @"&uacute;" : @"\u00FA",
                        @"&ucirc;" : @"\u00FB",
                        @"&uuml;" : @"\u00FC",
                        @"&yacute;" : @"\u00FD",
                        @"&thorn;" : @"\u00FE",
                        @"&yuml;" : @"\u00FF",
                        @"&OElig;" : @"\u0152",
                        @"&oelig;" : @"\u0153",
                        @"&Scaron;" : @"\u0160",
                        @"&scaron;" : @"\u0161",
                        @"&Yuml;" : @"\u0178",
                        @"&fnof;" : @"\u0192",
                        @"&circ;" : @"\u02C6",
                        @"&tilde;" : @"\u02DC",
                        @"&Alpha;" : @"\u0391",
                        @"&Beta;" : @"\u0392",
                        @"&Gamma;" : @"\u0393",
                        @"&Delta;" : @"\u0394",
                        @"&Epsilon;" : @"\u0395",
                        @"&Zeta;" : @"\u0396",
                        @"&Eta;" : @"\u0397",
                        @"&Theta;" : @"\u0398",
                        @"&Iota;" : @"\u0399",
                        @"&Kappa;" : @"\u039A",
                        @"&Lambda;" : @"\u039B",
                        @"&Mu;" : @"\u039C",
                        @"&Nu;" : @"\u039D",
                        @"&Xi;" : @"\u039E",
                        @"&Omicron;" : @"\u039F",
                        @"&Pi;" : @"\u03A0",
                        @"&Rho;" : @"\u03A1",
                        @"&Sigma;" : @"\u03A3",
                        @"&Tau;" : @"\u03A4",
                        @"&Upsilon;" : @"\u03A5",
                        @"&Phi;" : @"\u03A6",
                        @"&Chi;" : @"\u03A7",
                        @"&Psi;" : @"\u03A8",
                        @"&Omega;" : @"\u03A9",
                        @"&alpha;" : @"\u03B1",
                        @"&beta;" : @"\u03B2",
                        @"&gamma;" : @"\u03B3",
                        @"&delta;" : @"\u03B4",
                        @"&epsilon;" : @"\u03B5",
                        @"&zeta;" : @"\u03B6",
                        @"&eta;" : @"\u03B7",
                        @"&theta;" : @"\u03B8",
                        @"&iota;" : @"\u03B9",
                        @"&kappa;" : @"\u03BA",
                        @"&lambda;" : @"\u03BB",
                        @"&mu;" : @"\u03BC",
                        @"&nu;" : @"\u03BD",
                        @"&xi;" : @"\u03BE",
                        @"&omicron;" : @"\u03BF",
                        @"&pi;" : @"\u03C0",
                        @"&rho;" : @"\u03C1",
                        @"&sigmaf;" : @"\u03C2",
                        @"&sigma;" : @"\u03C3",
                        @"&tau;" : @"\u03C4",
                        @"&upsilon;" : @"\u03C5",
                        @"&phi;" : @"\u03C6",
                        @"&chi;" : @"\u03C7",
                        @"&psi;" : @"\u03C8",
                        @"&omega;" : @"\u03C9",
                        @"&thetasym;" : @"\u03D1",
                        @"&upsih;" : @"\u03D2",
                        @"&piv;" : @"\u03D6",
                        @"&ensp;" : @"\u2002",
                        @"&emsp;" : @"\u2003",
                        @"&thinsp;" : @"\u2009",
                        @"&zwnj;" : @"\u200C",
                        @"&zwj;" : @"\u200D",
                        @"&lrm;" : @"\u200E",
                        @"&rlm;" : @"\u200F",
                        @"&ndash;" : @"\u2013",
                        @"&mdash;" : @"\u2014",
                        @"&lsquo;" : @"\u2018",
                        @"&rsquo;" : @"\u2019",
                        @"&sbquo;" : @"\u201A",
                        @"&ldquo;" : @"\u201C",
                        @"&rdquo;" : @"\u201D",
                        @"&bdquo;" : @"\u201E",
                        @"&dagger;" : @"\u2020",
                        @"&Dagger;" : @"\u2021",
                        @"&bull;" : @"\u2022",
                        @"&hellip;" : @"\u2026",
                        @"&permil;" : @"\u2030",
                        @"&prime;" : @"\u2032",
                        @"&Prime;" : @"\u2033",
                        @"&lsaquo;" : @"\u2039",
                        @"&rsaquo;" : @"\u203A",
                        @"&oline;" : @"\u203E",
                        @"&frasl;" : @"\u2044",
                        @"&euro;" : @"\u20AC",
                        @"&image;" : @"\u2111",
                        @"&weierp;" : @"\u2118",
                        @"&real;" : @"\u211C",
                        @"&trade;" : @"\u2122",
                        @"&alefsym;" : @"\u2135",
                        @"&larr;" : @"\u2190",
                        @"&uarr;" : @"\u2191",
                        @"&rarr;" : @"\u2192",
                        @"&darr;" : @"\u2193",
                        @"&harr;" : @"\u2194",
                        @"&crarr;" : @"\u21B5",
                        @"&lArr;" : @"\u21D0",
                        @"&uArr;" : @"\u21D1",
                        @"&rArr;" : @"\u21D2",
                        @"&dArr;" : @"\u21D3",
                        @"&hArr;" : @"\u21D4",
                        @"&forall;" : @"\u2200",
                        @"&part;" : @"\u2202",
                        @"&exist;" : @"\u2203",
                        @"&empty;" : @"\u2205",
                        @"&nabla;" : @"\u2207",
                        @"&isin;" : @"\u2208",
                        @"&notin;" : @"\u2209",
                        @"&ni;" : @"\u220B",
                        @"&prod;" : @"\u220F",
                        @"&sum;" : @"\u2211",
                        @"&minus;" : @"\u2212",
                        @"&lowast;" : @"\u2217",
                        @"&radic;" : @"\u221A",
                        @"&prop;" : @"\u221D",
                        @"&infin;" : @"\u221E",
                        @"&ang;" : @"\u2220",
                        @"&and;" : @"\u2227",
                        @"&or;" : @"\u2228",
                        @"&cap;" : @"\u2229",
                        @"&cup;" : @"\u222A",
                        @"&int;" : @"\u222B",
                        @"&there4;" : @"\u2234",
                        @"&sim;" : @"\u223C",
                        @"&cong;" : @"\u2245",
                        @"&asymp;" : @"\u2248",
                        @"&ne;" : @"\u2260",
                        @"&equiv;" : @"\u2261",
                        @"&le;" : @"\u2264",
                        @"&ge;" : @"\u2265",
                        @"&sub;" : @"\u2282",
                        @"&sup;" : @"\u2283",
                        @"&nsub;" : @"\u2284",
                        @"&sube;" : @"\u2286",
                        @"&supe;" : @"\u2287",
                        @"&oplus;" : @"\u2295",
                        @"&otimes;" : @"\u2297",
                        @"&perp;" : @"\u22A5",
                        @"&sdot;" : @"\u22C5",
                        @"&vellip;" : @"\u22EE",
                        @"&lceil;" : @"\u2308",
                        @"&rceil;" : @"\u2309",
                        @"&lfloor;" : @"\u230A",
                        @"&rfloor;" : @"\u230B",
                        @"&lang;" : @"\u2329",
                        @"&rang;" : @"\u232A",
                        @"&loz;" : @"\u25CA",
                        @"&spades;" : @"\u2660",
                        @"&clubs;" : @"\u2663",
                        @"&hearts;" : @"\u2665",
                        @"&diams;" : @"\u2666",
                        @"&#32;" : @" ",
                        @"&#33;" : @"!",
                        @"&#34;" : @"\"",
                        @"&#35;" : @"#",
                        @"&#36;" : @"$",
                        @"&#37;" : @"%",
                        @"&#38;" : @"&",
                        @"&#39;" : @"'",
                        @"&#40;" : @"(",
                        @"&#41;" : @")",
                        @"&#42;" : @"*",
                        @"&#43;" : @"+",
                        @"&#44;" : @",",
                        @"&#45;" : @"-",
                        @"&#46;" : @".",
                        @"&#47;" : @"/",
                        @"&#48;" : @"0",
                        @"&#49;" : @"1",
                        @"&#50;" : @"2",
                        @"&#51;" : @"3",
                        @"&#52;" : @"4",
                        @"&#53;" : @"5",
                        @"&#54;" : @"6",
                        @"&#55;" : @"7",
                        @"&#56;" : @"8",
                        @"&#57;" : @"9",
                        @"&#58;" : @":",
                        @"&#59;" : @";",
                        @"&#60;" : @"<",
                        @"&#61;" : @"=",
                        @"&#62;" : @">",
                        @"&#63;" : @"?",
                        @"&#64;" : @"@",
                        @"&#65;" : @"A",
                        @"&#66;" : @"B",
                        @"&#67;" : @"C",
                        @"&#68;" : @"D",
                        @"&#69;" : @"E",
                        @"&#70;" : @"F",
                        @"&#71;" : @"G",
                        @"&#72;" : @"H",
                        @"&#73;" : @"I",
                        @"&#74;" : @"J",
                        @"&#75;" : @"K",
                        @"&#76;" : @"L",
                        @"&#77;" : @"M",
                        @"&#78;" : @"N",
                        @"&#79;" : @"O",
                        @"&#80;" : @"P",
                        @"&#81;" : @"Q",
                        @"&#82;" : @"R",
                        @"&#83;" : @"S",
                        @"&#84;" : @"T",
                        @"&#85;" : @"U",
                        @"&#86;" : @"V",
                        @"&#87;" : @"W",
                        @"&#88;" : @"X",
                        @"&#89;" : @"Y",
                        @"&#90;" : @"Z",
                        @"&#91;" : @"[",
                        @"&#92;" : @"\\",
                        @"&#93;" : @"]",
                        @"&#94;" : @"^",
                        @"&#95;" : @"_",
                        @"&#96;" : @"`",
                        @"&#97;" : @"a",
                        @"&#98;" : @"b",
                        @"&#99;" : @"c",
                        @"&#100;" : @"d",
                        @"&#101;" : @"e",
                        @"&#102;" : @"f",
                        @"&#103;" : @"g",
                        @"&#104;" : @"h",
                        @"&#105;" : @"i",
                        @"&#106;" : @"j",
                        @"&#107;" : @"k",
                        @"&#108;" : @"l",
                        @"&#109;" : @"m",
                        @"&#110;" : @"n",
                        @"&#111;" : @"o",
                        @"&#112;" : @"p",
                        @"&#113;" : @"q",
                        @"&#114;" : @"r",
                        @"&#115;" : @"s",
                        @"&#116;" : @"t",
                        @"&#117;" : @"u",
                        @"&#118;" : @"v",
                        @"&#119;" : @"w",
                        @"&#120;" : @"x",
                        @"&#121;" : @"y",
                        @"&#122;" : @"z",
                        @"&#123;" : @"{",
                        @"&#124;" : @"|",
                        @"&#125;" : @"}",
                        @"&#126;" : @"~",
                        @"&#127;" : @"\u0127",
                        @"&#128;" : @"\u0128",
                        @"&#129;" : @"\u0129",
                        @"&#130;" : @"\u0130",
                        @"&#131;" : @"\u0131",
                        @"&#132;" : @"\u0132",
                        @"&#133;" : @"\u0133",
                        @"&#134;" : @"\u0134",
                        @"&#135;" : @"\u0135",
                        @"&#136;" : @"\u0136",
                        @"&#137;" : @"\u0137",
                        @"&#138;" : @"\u0138",
                        @"&#139;" : @"\u0139",
                        @"&#140;" : @"\u0140",
                        @"&#141;" : @"\u0141",
                        @"&#142;" : @"\u0142",
                        @"&#143;" : @"\u0143",
                        @"&#144;" : @"\u0144",
                        @"&#145;" : @"\u0145",
                        @"&#146;" : @"\u0146",
                        @"&#147;" : @"\u0147",
                        @"&#148;" : @"\u0148",
                        @"&#149;" : @"\u0149",
                        @"&#150;" : @"\u0150",
                        @"&#151;" : @"\u0151",
                        @"&#152;" : @"\u0152",
                        @"&#153;" : @"\u0153",
                        @"&#154;" : @"\u0154",
                        @"&#155;" : @"\u0155",
                        @"&#156;" : @"\u0156",
                        @"&#157;" : @"\u0157",
                        @"&#158;" : @"\u0158",
                        @"&#159;" : @"\u0159",
                        @"&#160;" : @"\u00A0",
                        @"&#161;" : @"\u00A1",
                        @"&#162;" : @"\u00A2",
                        @"&#163;" : @"\u00A3",
                        @"&#164;" : @"\u00A4",
                        @"&#165;" : @"\u00A5",
                        @"&#166;" : @"\u00A6",
                        @"&#167;" : @"\u00A7",
                        @"&#168;" : @"\u00A8",
                        @"&#169;" : @"\u00A9",
                        @"&#170;" : @"\u00AA",
                        @"&#171;" : @"\u00AB",
                        @"&#172;" : @"\u00AC",
                        @"&#173;" : @"\u00AD",
                        @"&#174;" : @"\u00AE",
                        @"&#175;" : @"\u00AF",
                        @"&#176;" : @"\u00B0",
                        @"&#177;" : @"\u00B1",
                        @"&#178;" : @"\u00B2",
                        @"&#179;" : @"\u00B3",
                        @"&#180;" : @"\u00B4",
                        @"&#181;" : @"\u00B5",
                        @"&#182;" : @"\u00B6",
                        @"&#183;" : @"\u00B7",
                        @"&#184;" : @"\u00B8",
                        @"&#185;" : @"\u00B9",
                        @"&#186;" : @"\u00BA",
                        @"&#187;" : @"\u00BB",
                        @"&#188;" : @"\u00BC",
                        @"&#189;" : @"\u00BD",
                        @"&#190;" : @"\u00BE",
                        @"&#191;" : @"\u00BF",
                        @"&#192;" : @"\u00C0",
                        @"&#193;" : @"\u00C1",
                        @"&#194;" : @"\u00C2",
                        @"&#195;" : @"\u00C3",
                        @"&#196;" : @"\u00C4",
                        @"&#197;" : @"\u00C5",
                        @"&#198;" : @"\u00C6",
                        @"&#199;" : @"\u00C7",
                        @"&#200;" : @"\u00C8",
                        @"&#201;" : @"\u00C9",
                        @"&#202;" : @"\u00CA",
                        @"&#203;" : @"\u00CB",
                        @"&#204;" : @"\u00CC",
                        @"&#205;" : @"\u00CD",
                        @"&#206;" : @"\u00CE",
                        @"&#207;" : @"\u00CF",
                        @"&#208;" : @"\u00D0",
                        @"&#209;" : @"\u00D1",
                        @"&#210;" : @"\u00D2",
                        @"&#211;" : @"\u00D3",
                        @"&#212;" : @"\u00D4",
                        @"&#213;" : @"\u00D5",
                        @"&#214;" : @"\u00D6",
                        @"&#215;" : @"\u00D7",
                        @"&#216;" : @"\u00D8",
                        @"&#217;" : @"\u00D9",
                        @"&#218;" : @"\u00DA",
                        @"&#219;" : @"\u00DB",
                        @"&#220;" : @"\u00DC",
                        @"&#221;" : @"\u00DD",
                        @"&#222;" : @"\u00DE",
                        @"&#223;" : @"\u00DF",
                        @"&#224;" : @"\u00E0",
                        @"&#225;" : @"\u00E1",
                        @"&#226;" : @"\u00E2",
                        @"&#227;" : @"\u00E3",
                        @"&#228;" : @"\u00E4",
                        @"&#229;" : @"\u00E5",
                        @"&#230;" : @"\u00E6",
                        @"&#231;" : @"\u00E7",
                        @"&#232;" : @"\u00E8",
                        @"&#233;" : @"\u00E9",
                        @"&#234;" : @"\u00EA",
                        @"&#235;" : @"\u00EB",
                        @"&#236;" : @"\u00EC",
                        @"&#237;" : @"\u00ED",
                        @"&#238;" : @"\u00EE",
                        @"&#239;" : @"\u00EF",
                        @"&#240;" : @"\u00F0",
                        @"&#241;" : @"\u00F1",
                        @"&#242;" : @"\u00F2",
                        @"&#243;" : @"\u00F3",
                        @"&#244;" : @"\u00F4",
                        @"&#245;" : @"\u00F5",
                        @"&#246;" : @"\u00F6",
                        @"&#247;" : @"\u00F7",
                        @"&#248;" : @"\u00F8",
                        @"&#249;" : @"\u00F9",
                        @"&#250;" : @"\u00FA",
                        @"&#251;" : @"\u00FB",
                        @"&#252;" : @"\u00FC",
                        @"&#253;" : @"\u00FD",
                        @"&#254;" : @"\u00FE",
                        @"&#255;" : @"\u00FF",
                        @"&#402;" : @"\u0192",
                        @"&#913;" : @"\u0391",
                        @"&#914;" : @"\u0392",
                        @"&#915;" : @"\u0393",
                        @"&#916;" : @"\u0394",
                        @"&#917;" : @"\u0395",
                        @"&#918;" : @"\u0396",
                        @"&#919;" : @"\u0397",
                        @"&#920;" : @"\u0398",
                        @"&#921;" : @"\u0399",
                        @"&#922;" : @"\u039A",
                        @"&#923;" : @"\u039B",
                        @"&#924;" : @"\u039C",
                        @"&#925;" : @"\u039D",
                        @"&#926;" : @"\u039E",
                        @"&#927;" : @"\u039F",
                        @"&#928;" : @"\u03A0",
                        @"&#929;" : @"\u03A1",
                        @"&#931;" : @"\u03A3",
                        @"&#932;" : @"\u03A4",
                        @"&#933;" : @"\u03A5",
                        @"&#934;" : @"\u03A6",
                        @"&#935;" : @"\u03A7",
                        @"&#936;" : @"\u03A8",
                        @"&#937;" : @"\u03A9",
                        @"&#945;" : @"\u03B1",
                        @"&#946;" : @"\u03B2",
                        @"&#947;" : @"\u03B3",
                        @"&#948;" : @"\u03B4",
                        @"&#949;" : @"\u03B5",
                        @"&#950;" : @"\u03B6",
                        @"&#951;" : @"\u03B7",
                        @"&#952;" : @"\u03B8",
                        @"&#953;" : @"\u03B9",
                        @"&#954;" : @"\u03BA",
                        @"&#955;" : @"\u03BB",
                        @"&#956;" : @"\u03BC",
                        @"&#957;" : @"\u03BD",
                        @"&#958;" : @"\u03BE",
                        @"&#959;" : @"\u03BF",
                        @"&#960;" : @"\u03C0",
                        @"&#961;" : @"\u03C1",
                        @"&#962;" : @"\u03C2",
                        @"&#963;" : @"\u03C3",
                        @"&#964;" : @"\u03C4",
                        @"&#965;" : @"\u03C5",
                        @"&#966;" : @"\u03C6",
                        @"&#967;" : @"\u03C7",
                        @"&#968;" : @"\u03C8",
                        @"&#969;" : @"\u03C9",
                        @"&#977;" : @"\u03D1",
                        @"&#978;" : @"\u03D2",
                        @"&#982;" : @"\u03D6",
                        @"&#8226;" : @"\u2022",
                        @"&#8230;" : @"\u2026",
                        @"&#8242;" : @"\u2032",
                        @"&#8243;" : @"\u2033",
                        @"&#8254;" : @"\u203E",
                        @"&#8260;" : @"\u2044",
                        @"&#8472;" : @"\u2118",
                        @"&#8465;" : @"\u2111",
                        @"&#8476;" : @"\u211C",
                        @"&#8482;" : @"\u2122",
                        @"&#8501;" : @"\u2135",
                        @"&#8592;" : @"\u2190",
                        @"&#8593;" : @"\u2191",
                        @"&#8594;" : @"\u2192",
                        @"&#8595;" : @"\u2193",
                        @"&#8596;" : @"\u2194",
                        @"&#8629;" : @"\u21B5",
                        @"&#8656;" : @"\u21D0",
                        @"&#8657;" : @"\u21D1",
                        @"&#8658;" : @"\u21D2",
                        @"&#8659;" : @"\u21D3",
                        @"&#8660;" : @"\u21D4",
                        @"&#8704;" : @"\u2200",
                        @"&#8706;" : @"\u2202",
                        @"&#8707;" : @"\u2203",
                        @"&#8709;" : @"\u2205",
                        @"&#8711;" : @"\u2207",
                        @"&#8712;" : @"\u2208",
                        @"&#8713;" : @"\u2209",
                        @"&#8715;" : @"\u220B",
                        @"&#8719;" : @"\u220F",
                        @"&#8721;" : @"\u2211",
                        @"&#8722;" : @"\u2212",
                        @"&#8727;" : @"\u2217",
                        @"&#8730;" : @"\u221A",
                        @"&#8733;" : @"\u221D",
                        @"&#8734;" : @"\u221E",
                        @"&#8736;" : @"\u2220",
                        @"&#8743;" : @"\u2227",
                        @"&#8744;" : @"\u2228",
                        @"&#8745;" : @"\u2229",
                        @"&#8746;" : @"\u222A",
                        @"&#8747;" : @"\u222B",
                        @"&#8756;" : @"\u2234",
                        @"&#8764;" : @"\u223C",
                        @"&#8773;" : @"\u2245",
                        @"&#8776;" : @"\u2248",
                        @"&#8800;" : @"\u2260",
                        @"&#8801;" : @"\u2261",
                        @"&#8804;" : @"\u2264",
                        @"&#8805;" : @"\u2265",
                        @"&#8834;" : @"\u2282",
                        @"&#8835;" : @"\u2283",
                        @"&#8836;" : @"\u2284",
                        @"&#8838;" : @"\u2286",
                        @"&#8839;" : @"\u2287",
                        @"&#8853;" : @"\u2295",
                        @"&#8855;" : @"\u2297",
                        @"&#8869;" : @"\u22A5",
                        @"&#8901;" : @"\u22C5",
                        @"&#8968;" : @"\u2308",
                        @"&#8969;" : @"\u2309",
                        @"&#8970;" : @"\u230A",
                        @"&#8971;" : @"\u230B",
                        @"&#9001;" : @"\u2329",
                        @"&#9002;" : @"\u232A",
                        @"&#9674;" : @"\u25CA",
                        @"&#9824;" : @"\u2660",
                        @"&#9827;" : @"\u2663",
                        @"&#9829;" : @"\u2665",
                        @"&#9830;" : @"\u2666",
                        @"&#x20;" : @" ",
                        @"&#x21;" : @"!",
                        @"&#x22;" : @"\"",
                        @"&#x23;" : @"#",
                        @"&#x24;" : @"$",
                        @"&#x25;" : @"%",
                        @"&#x26;" : @"&",
                        @"&#x27;" : @"'",
                        @"&#x28;" : @"(",
                        @"&#x29;" : @")",
                        @"&#x2A;" : @"*",
                        @"&#x2B;" : @"+",
                        @"&#x2C;" : @",",
                        @"&#x2D;" : @"-",
                        @"&#x2E;" : @".",
                        @"&#x2F;" : @"/",
                        @"&#x30;" : @"0",
                        @"&#x31;" : @"1",
                        @"&#x32;" : @"2",
                        @"&#x33;" : @"3",
                        @"&#x34;" : @"4",
                        @"&#x35;" : @"5",
                        @"&#x36;" : @"6",
                        @"&#x37;" : @"7",
                        @"&#x38;" : @"8",
                        @"&#x39;" : @"9",
                        @"&#x3A;" : @":",
                        @"&#x3B;" : @";",
                        @"&#x3C;" : @"<",
                        @"&#x3D;" : @"=",
                        @"&#x3E;" : @">",
                        @"&#x3F;" : @"?",
                        @"&#x40;" : @"@",
                        @"&#x41;" : @"A",
                        @"&#x42;" : @"B",
                        @"&#x43;" : @"C",
                        @"&#x44;" : @"D",
                        @"&#x45;" : @"E",
                        @"&#x46;" : @"F",
                        @"&#x47;" : @"G",
                        @"&#x48;" : @"H",
                        @"&#x49;" : @"I",
                        @"&#x4A;" : @"J",
                        @"&#x4B;" : @"K",
                        @"&#x4C;" : @"L",
                        @"&#x4D;" : @"M",
                        @"&#x4E;" : @"N",
                        @"&#x4F;" : @"O",
                        @"&#x50;" : @"P",
                        @"&#x51;" : @"Q",
                        @"&#x52;" : @"R",
                        @"&#x53;" : @"S",
                        @"&#x54;" : @"T",
                        @"&#x55;" : @"U",
                        @"&#x56;" : @"V",
                        @"&#x57;" : @"W",
                        @"&#x58;" : @"X",
                        @"&#x59;" : @"Y",
                        @"&#x5A;" : @"Z",
                        @"&#x5B;" : @"[",
                        @"&#x5C;" : @"\\",
                        @"&#x5D;" : @"]",
                        @"&#x5E;" : @"^",
                        @"&#x5F;" : @"_",
                        @"&#x60;" : @"`",
                        @"&#x61;" : @"a",
                        @"&#x62;" : @"b",
                        @"&#x63;" : @"c",
                        @"&#x64;" : @"d",
                        @"&#x65;" : @"e",
                        @"&#x66;" : @"f",
                        @"&#x67;" : @"g",
                        @"&#x68;" : @"h",
                        @"&#x69;" : @"i",
                        @"&#x6A;" : @"j",
                        @"&#x6B;" : @"k",
                        @"&#x6C;" : @"l",
                        @"&#x6D;" : @"m",
                        @"&#x6E;" : @"n",
                        @"&#x6F;" : @"o",
                        @"&#x70;" : @"p",
                        @"&#x71;" : @"q",
                        @"&#x72;" : @"r",
                        @"&#x73;" : @"s",
                        @"&#x74;" : @"t",
                        @"&#x75;" : @"u",
                        @"&#x76;" : @"v",
                        @"&#x77;" : @"w",
                        @"&#x78;" : @"x",
                        @"&#x79;" : @"y",
                        @"&#x7A;" : @"z",
                        @"&#x7B;" : @"{",
                        @"&#x7C;" : @"|",
                        @"&#x7D;" : @"}",
                        @"&#x7E;" : @"~",
                        @"&#x7F;" : @"\u0127",
                        @"&#x80;" : @"\u0128",
                        @"&#x81;" : @"\u0129",
                        @"&#x82;" : @"\u0130",
                        @"&#x83;" : @"\u0131",
                        @"&#x84;" : @"\u0132",
                        @"&#x85;" : @"\u0133",
                        @"&#x86;" : @"\u0134",
                        @"&#x87;" : @"\u0135",
                        @"&#x88;" : @"\u0136",
                        @"&#x89;" : @"\u0137",
                        @"&#x8A;" : @"\u0138",
                        @"&#x8B;" : @"\u0139",
                        @"&#x8C;" : @"\u0140",
                        @"&#x8D;" : @"\u0141",
                        @"&#x8E;" : @"\u0142",
                        @"&#x8F;" : @"\u0143",
                        @"&#x90;" : @"\u0144",
                        @"&#x91;" : @"\u0145",
                        @"&#x92;" : @"\u0146",
                        @"&#x93;" : @"\u0147",
                        @"&#x94;" : @"\u0148",
                        @"&#x95;" : @"\u0149",
                        @"&#x96;" : @"\u0150",
                        @"&#x97;" : @"\u0151",
                        @"&#x98;" : @"\u0152",
                        @"&#x99;" : @"\u0153",
                        @"&#x9A;" : @"\u0154",
                        @"&#x9B;" : @"\u0155",
                        @"&#x9C;" : @"\u0156",
                        @"&#x9D;" : @"\u0157",
                        @"&#x9E;" : @"\u0158",
                        @"&#x9F;" : @"\u0159",
                        @"&#xA0;" : @"\u00A0",
                        @"&#xA1;" : @"\u00A1",
                        @"&#xA2;" : @"\u00A2",
                        @"&#xA3;" : @"\u00A3",
                        @"&#xA4;" : @"\u00A4",
                        @"&#xA5;" : @"\u00A5",
                        @"&#xA6;" : @"\u00A6",
                        @"&#xA7;" : @"\u00A7",
                        @"&#xA8;" : @"\u00A8",
                        @"&#xA9;" : @"\u00A9",
                        @"&#xAA;" : @"\u00AA",
                        @"&#xAB;" : @"\u00AB",
                        @"&#xAC;" : @"\u00AC",
                        @"&#xAD;" : @"\u00AD",
                        @"&#xAE;" : @"\u00AE",
                        @"&#xAF;" : @"\u00AF",
                        @"&#xB0;" : @"\u00B0",
                        @"&#xB1;" : @"\u00B1",
                        @"&#xB2;" : @"\u00B2",
                        @"&#xB3;" : @"\u00B3",
                        @"&#xB4;" : @"\u00B4",
                        @"&#xB5;" : @"\u00B5",
                        @"&#xB6;" : @"\u00B6",
                        @"&#xB7;" : @"\u00B7",
                        @"&#xB8;" : @"\u00B8",
                        @"&#xB9;" : @"\u00B9",
                        @"&#xBA;" : @"\u00BA",
                        @"&#xBB;" : @"\u00BB",
                        @"&#xBC;" : @"\u00BC",
                        @"&#xBD;" : @"\u00BD",
                        @"&#xBE;" : @"\u00BE",
                        @"&#xBF;" : @"\u00BF",
                        @"&#xC0;" : @"\u00C0",
                        @"&#xC1;" : @"\u00C1",
                        @"&#xC2;" : @"\u00C2",
                        @"&#xC3;" : @"\u00C3",
                        @"&#xC4;" : @"\u00C4",
                        @"&#xC5;" : @"\u00C5",
                        @"&#xC6;" : @"\u00C6",
                        @"&#xC7;" : @"\u00C7",
                        @"&#xC8;" : @"\u00C8",
                        @"&#xC9;" : @"\u00C9",
                        @"&#xCA;" : @"\u00CA",
                        @"&#xCB;" : @"\u00CB",
                        @"&#xCC;" : @"\u00CC",
                        @"&#xCD;" : @"\u00CD",
                        @"&#xCE;" : @"\u00CE",
                        @"&#xCF;" : @"\u00CF",
                        @"&#xD0;" : @"\u00D0",
                        @"&#xD1;" : @"\u00D1",
                        @"&#xD2;" : @"\u00D2",
                        @"&#xD3;" : @"\u00D3",
                        @"&#xD4;" : @"\u00D4",
                        @"&#xD5;" : @"\u00D5",
                        @"&#xD6;" : @"\u00D6",
                        @"&#xD7;" : @"\u00D7",
                        @"&#xD8;" : @"\u00D8",
                        @"&#xD9;" : @"\u00D9",
                        @"&#xDA;" : @"\u00DA",
                        @"&#xDB;" : @"\u00DB",
                        @"&#xDC;" : @"\u00DC",
                        @"&#xDD;" : @"\u00DD",
                        @"&#xDE;" : @"\u00DE",
                        @"&#xDF;" : @"\u00DF",
                        @"&#xE0;" : @"\u00E0",
                        @"&#xE1;" : @"\u00E1",
                        @"&#xE2;" : @"\u00E2",
                        @"&#xE3;" : @"\u00E3",
                        @"&#xE4;" : @"\u00E4",
                        @"&#xE5;" : @"\u00E5",
                        @"&#xE6;" : @"\u00E6",
                        @"&#xE7;" : @"\u00E7",
                        @"&#xE8;" : @"\u00E8",
                        @"&#xE9;" : @"\u00E9",
                        @"&#xEA;" : @"\u00EA",
                        @"&#xEB;" : @"\u00EB",
                        @"&#xEC;" : @"\u00EC",
                        @"&#xED;" : @"\u00ED",
                        @"&#xEE;" : @"\u00EE",
                        @"&#xEF;" : @"\u00EF",
                        @"&#xF0;" : @"\u00F0",
                        @"&#xF1;" : @"\u00F1",
                        @"&#xF2;" : @"\u00F2",
                        @"&#xF3;" : @"\u00F3",
                        @"&#xF4;" : @"\u00F4",
                        @"&#xF5;" : @"\u00F5",
                        @"&#xF6;" : @"\u00F6",
                        @"&#xF7;" : @"\u00F7",
                        @"&#xF8;" : @"\u00F8",
                        @"&#xF9;" : @"\u00F9",
                        @"&#xFA;" : @"\u00FA",
                        @"&#xFB;" : @"\u00FB",
                        @"&#xFC;" : @"\u00FC",
                        @"&#xFD;" : @"\u00FD",
                        @"&#xFE;" : @"\u00FE",
                        @"&#xFF;" : @"\u00FF",
                        @"&#x192;" : @"\u0192",
                        @"&#x391;" : @"\u0391",
                        @"&#x392;" : @"\u0392",
                        @"&#x393;" : @"\u0393",
                        @"&#x394;" : @"\u0394",
                        @"&#x395;" : @"\u0395",
                        @"&#x396;" : @"\u0396",
                        @"&#x397;" : @"\u0397",
                        @"&#x398;" : @"\u0398",
                        @"&#x399;" : @"\u0399",
                        @"&#x39A;" : @"\u039A",
                        @"&#x39B;" : @"\u039B",
                        @"&#x39C;" : @"\u039C",
                        @"&#x39D;" : @"\u039D",
                        @"&#x39E;" : @"\u039E",
                        @"&#x39F;" : @"\u039F",
                        @"&#x3A0;" : @"\u03A0",
                        @"&#x3A1;" : @"\u03A1",
                        @"&#x3A3;" : @"\u03A3",
                        @"&#x3A4;" : @"\u03A4",
                        @"&#x3A5;" : @"\u03A5",
                        @"&#x3A6;" : @"\u03A6",
                        @"&#x3A7;" : @"\u03A7",
                        @"&#x3A8;" : @"\u03A8",
                        @"&#x3A9;" : @"\u03A9",
                        @"&#x3B1;" : @"\u03B1",
                        @"&#x3B2;" : @"\u03B2",
                        @"&#x3B3;" : @"\u03B3",
                        @"&#x3B4;" : @"\u03B4",
                        @"&#x3B5;" : @"\u03B5",
                        @"&#x3B6;" : @"\u03B6",
                        @"&#x3B7;" : @"\u03B7",
                        @"&#x3B8;" : @"\u03B8",
                        @"&#x3B9;" : @"\u03B9",
                        @"&#x3BA;" : @"\u03BA",
                        @"&#x3BB;" : @"\u03BB",
                        @"&#x3BC;" : @"\u03BC",
                        @"&#x3BD;" : @"\u03BD",
                        @"&#x3BE;" : @"\u03BE",
                        @"&#x3BF;" : @"\u03BF",
                        @"&#x3C0;" : @"\u03C0",
                        @"&#x3C1;" : @"\u03C1",
                        @"&#x3C2;" : @"\u03C2",
                        @"&#x3C3;" : @"\u03C3",
                        @"&#x3C4;" : @"\u03C4",
                        @"&#x3C5;" : @"\u03C5",
                        @"&#x3C6;" : @"\u03C6",
                        @"&#x3C7;" : @"\u03C7",
                        @"&#x3C8;" : @"\u03C8",
                        @"&#x3C9;" : @"\u03C9",
                        @"&#x3D1;" : @"\u03D1",
                        @"&#x3D2;" : @"\u03D2",
                        @"&#x3D6;" : @"\u03D6",
                        @"&#x2022;" : @"\u2022",
                        @"&#x2026;" : @"\u2026",
                        @"&#x2032;" : @"\u2032",
                        @"&#x2033;" : @"\u2033",
                        @"&#x203E;" : @"\u203E",
                        @"&#x2044;" : @"\u2044",
                        @"&#x2118;" : @"\u2118",
                        @"&#x2111;" : @"\u2111",
                        @"&#x211C;" : @"\u211C",
                        @"&#x2122;" : @"\u2122",
                        @"&#x2135;" : @"\u2135",
                        @"&#x2190;" : @"\u2190",
                        @"&#x2191;" : @"\u2191",
                        @"&#x2192;" : @"\u2192",
                        @"&#x2193;" : @"\u2193",
                        @"&#x2194;" : @"\u2194",
                        @"&#x21B5;" : @"\u21B5",
                        @"&#x21D0;" : @"\u21D0",
                        @"&#x21D1;" : @"\u21D1",
                        @"&#x21D2;" : @"\u21D2",
                        @"&#x21D3;" : @"\u21D3",
                        @"&#x21D4;" : @"\u21D4",
                        @"&#x2200;" : @"\u2200",
                        @"&#x2202;" : @"\u2202",
                        @"&#x2203;" : @"\u2203",
                        @"&#x2205;" : @"\u2205",
                        @"&#x2207;" : @"\u2207",
                        @"&#x2208;" : @"\u2208",
                        @"&#x2209;" : @"\u2209",
                        @"&#x220B;" : @"\u220B",
                        @"&#x220F;" : @"\u220F",
                        @"&#x2211;" : @"\u2211",
                        @"&#x2212;" : @"\u2212",
                        @"&#x2217;" : @"\u2217",
                        @"&#x221A;" : @"\u221A",
                        @"&#x221D;" : @"\u221D",
                        @"&#x221E;" : @"\u221E",
                        @"&#x2220;" : @"\u2220",
                        @"&#x2227;" : @"\u2227",
                        @"&#x2228;" : @"\u2228",
                        @"&#x2229;" : @"\u2229",
                        @"&#x222A;" : @"\u222A",
                        @"&#x222B;" : @"\u222B",
                        @"&#x2234;" : @"\u2234",
                        @"&#x223C;" : @"\u223C",
                        @"&#x2245;" : @"\u2245",
                        @"&#x2248;" : @"\u2248",
                        @"&#x2260;" : @"\u2260",
                        @"&#x2261;" : @"\u2261",
                        @"&#x2264;" : @"\u2264",
                        @"&#x2265;" : @"\u2265",
                        @"&#x2282;" : @"\u2282",
                        @"&#x2283;" : @"\u2283",
                        @"&#x2284;" : @"\u2284",
                        @"&#x2286;" : @"\u2286",
                        @"&#x2287;" : @"\u2287",
                        @"&#x2295;" : @"\u2295",
                        @"&#x2297;" : @"\u2297",
                        @"&#x22A5;" : @"\u22A5",
                        @"&#x22C5;" : @"\u22C5",
                        @"&#x2308;" : @"\u2308",
                        @"&#x2309;" : @"\u2309",
                        @"&#x230A;" : @"\u230A",
                        @"&#x230B;" : @"\u230B",
                        @"&#x2329;" : @"\u2329",
                        @"&#x232A;" : @"\u232A",
                        @"&#x25CA;" : @"\u25CA",
                        @"&#x2660;" : @"\u2660",
                        @"&#x2663;" : @"\u2663",
                        @"&#x2665;" : @"\u2665",
                        @"&#x2666;" : @"\u2666"
                        };
    });
}
@end
